package com.voltmao.service.application.contract;

import com.alibaba.fastjson.JSONObject;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import com.voltmao.persistent.mapper.*;
import com.voltmao.persistent.model.*;
import com.voltmao.service.application.sys.MessageTemplateServiceImpl;
import com.voltmao.webpro.frame.dto.DataPage;
import com.voltmao.webpro.utils.DateUtil;
import com.voltmao.webpro.utils.NumberUtils;
import com.voltmao.webpro.utils.PropertiesUtils;
import com.voltmao.webpro.utils.StringUtils;
import com.voltmao.webpro.utils.file.DocUtil;
import com.voltmao.webpro.utils.file.FileUtils;
import com.voltmao.webpro.utils.file.Word2PDF;
import com.voltmao.webpro.utils.http.PostUtil;

import java.io.File;
import java.util.*;

/**
 * 渠道商合同审核管理服务接口
 *
 * @author zhanglin
 * @date 2018/04/10
 */
@Service
public class ProviderAuditServiceImpl {
    private static final Logger testLogger = LoggerFactory.getLogger("MY_TEST_LOGGER");
    private static final Logger pdfLogger = LoggerFactory.getLogger("PDF_LOGGER");

    @Autowired
    private ContractProviderMapper contractProviderMapper;
    @Autowired
    private ContractProviderAuditMapper contractProviderAuditMapper;
    @Autowired
    private ProviderUserMapper providerUserMapper;
    @Autowired
    private MessageTemplateServiceImpl messageTemplateService;
    @Autowired
    private SysUserInfoMapper sysUserInfoMapper;
    @Autowired
    ContractProviderGdbcMapper contractProviderGdbcMapper;
    @Autowired
    ContractProviderSdnxMapper contractProviderSdnxMapper;
    @Autowired
    private ThreadPoolTaskExecutor taskExecutor;

    /**
     * 主键
     */
    private final String DATAID = "dataId" ;
    /**
     * 审核状态
     */
    private final String FORDICSHZT = "forDicShzt" ;
    /**
     * 合同类型1
     */
    private final Integer TYPE1 = 1;
    /**
     * 合同类型2
     */
    private final Integer TYPE2 = 2;
    /**
     * 合同类型3
     */
    private final Integer TYPE3 = 3;

    /**
     * 审核表为主表，审核表分页数据及查询
     * 附属了合同表，参数信息待定
     * @param params 查询参数
     * @return 返回DataPage集合
     */
    public DataPage selecAuditDataPage(Map<String,Object> params){
        testLogger.info("待查询参数："+params.toString());
        System.out.println("待查询参数："+params.toString());
        DataPage dataPage = new DataPage();
        int pageIndex = StringUtils.parseInt(params.get("pageNumber")+"", 1);
        int pageSize = StringUtils.parseInt(params.get("pageSize")+"", 20);

        ContractProviderAuditCriteria example = new ContractProviderAuditCriteria();
        ContractProviderAuditCriteria.Criteria c = example.createCriteria();
        c.andIsDelEqualTo(0);
        if(params.size() > 0){
            if(StringUtils.isNotEmpty(params.get(DATAID))) {
                c.andDataIdEqualTo(params.get(DATAID)+"");
            }
            String forCorpEmployesUser = "forCorpEmployesUser" ;
            if(StringUtils.isNotEmpty(params.get(forCorpEmployesUser))) {
                c.andForCorpEmployesUserEqualTo(params.get(forCorpEmployesUser)+"");
            }

            if(StringUtils.isNotEmpty(params.get(FORDICSHZT))) {
                c.andForDicShztEqualTo(params.get(FORDICSHZT)+"");
            }
            String forContractProvider = "forContractProvider" ;
            if(StringUtils.isNotEmpty(params.get(forContractProvider))) {
                c.andForContractProviderEqualTo(params.get(forContractProvider)+"");
            }
            String auditReason = "auditReason" ;
            if(StringUtils.isNotEmpty(params.get(auditReason))) {
                c.andAuditReasonLike("%" + params.get(auditReason) + "%");
            }
        }
        example.setOrderByClause("contract_provider_audit.create_date desc");
        List<Map<String, Object>> audits = contractProviderAuditMapper.selectMapByExample(example);
        for(Map<String, Object> tmpMap:audits){
            ContractProvider cp = contractProviderMapper.selectByPrimaryKey(tmpMap.get("forContractProvider")+"");
            tmpMap.put("contractType",cp.getForDicHtlx());
        }
        int totals = contractProviderAuditMapper.countByExample(example);

        dataPage.pageindex= pageIndex;
        dataPage.pagesize = pageSize;
        dataPage.rows = audits;
        dataPage.total = totals;
        return dataPage;
    }

    @Transactional(rollbackFor = Exception.class)
    public void insertOrUpdateAudit(Map<String, Object> params) throws IllegalArgumentException{
        testLogger.info("待修改或新增参数："+params.toString());
        System.out.println("待修改或新增参数："+params.toString());
        String fromId = sysUserInfoMapper.getZJName();
        //type=0,类型不存在
        //type=1,按全年签约量\年化合同金额
        //type=2,固定分成
        //type=3,售电能效
        int type = NumberUtils.parseInt(params.get("type")+"",0);

        ContractProviderAudit cpAudit = (ContractProviderAudit) PropertiesUtils.mapToObject(params,ContractProviderAudit.class);
        if(StringUtils.isNotEmpty(params.get(DATAID))){
            //更新
            cpAudit.setUpdateDate(new Date());
            ContractProviderAudit cpgAudit = contractProviderAuditMapper.selectByPrimaryKey(params.get("dataId")+"");
            String oldCode = cpgAudit.getForDicShzt();
            String newCode = params.get(FORDICSHZT)+"";
            if(isChangeOk(oldCode, newCode)){
                //可以修改审核状态
                contractProviderAuditMapper.updateByPrimaryKeySelective(cpAudit);
                String allPass = "4";
                if(allPass.equals(newCode)){
                    //添加为正式渠道商
                    ContractProvider cp = contractProviderMapper.selectByPrimaryKey(cpgAudit.getForContractProvider());
                    String toId = cp.getForProviderUser();
                    ProviderUser pu = providerUserMapper.selectByPrimaryKey(toId);
                    pu.setForDicQdshzt("3");
                    pu.setUpdateDate(new Date());
                    providerUserMapper.updateByPrimaryKeySelective(pu);
                    messageTemplateService.contractSecondAuditToProvider(fromId, toId);
                }
                //发消息
                if(oldCode.equals(TYPE2+"")){
                    boolean isPass = false;
                    ProviderUser pu = providerUserMapper.getDataId(params.get("dataId")+"");
                    if(newCode.equals(allPass)){
                        isPass = true;
                    }
                    messageTemplateService.contractSecondAudit(fromId,pu.getForCorpEmployesUser(),pu.getDataId(),isPass);
                }
            } else{
                //抛出异常，不合理的审核状态更改
                throw new IllegalArgumentException("审核状态不合理");
            }
        }else{//新增
            cpAudit.setDataId(StringUtils.uuid36());
            cpAudit.setCreateDate(new Date());
            cpAudit.setIsDel(0);
            if(isChangeOk(null, params.get(FORDICSHZT)+"")){
                contractProviderAuditMapper.insertSelective(cpAudit);
                //发送消息

                String providerId = contractProviderMapper.selectByPrimaryKey(params.get("forContractProvider")+"").getForProviderUser();
                String toId =providerUserMapper.selectByPrimaryKey(providerId).getForCorpEmployesUser();
                boolean isPass = false;
                String dicShzt = params.get(FORDICSHZT)+"";
                if(dicShzt.equals(TYPE2+"")) {
                    isPass = true;
                    setContractNo(params.get("forContractProvider")+"");
                }
                messageTemplateService.contractFirstAudit(fromId, toId, providerId, isPass);
            }else{
                //抛出异常，不合理的初始化审核状态
                throw new IllegalArgumentException();
            }
        }

    }

    /**
     * 根据类型和主键停用一条记录
     * @param type 合同类型
     * @param dataId 审核表主键
     */
    public void deleteAudit(String type, String dataId){
        testLogger.info("待删除主键："+dataId+";  类型:"+type);
        System.out.println("待删除主键："+dataId+";  类型:"+type);
        ContractProviderAudit cpAudit = contractProviderAuditMapper.selectByPrimaryKey(dataId);
        cpAudit.setUpdateDate(new Date());
        cpAudit.setIsDel(1);
        contractProviderAuditMapper.updateByPrimaryKey(cpAudit);
    }

    /**
     * 判断状态是否可以转换，如果不可转换，返回false
     * 如果是扫描件审核不通过，要改成审核通过，也会返回false
     * @param oldCode 转换之前
     * @param newCode 待转换结果
     * @return 可以转换为true
     */
    private static boolean isChangeOk(String oldCode, String newCode){
        testLogger.info("前后转换的两个值："+oldCode+"||"+ newCode);
        System.out.println("前后转换的两个值："+oldCode+"||"+ newCode);
        if(StringUtils.isEmpty(newCode)){
            return false;
        }
        String[] str1 = {"2","1"};
        String[] str2 = {"4","3"};
        List<String> list1 = Arrays.asList(str1);
        List<String> list2 = Arrays.asList(str2);
        if(StringUtils.isEmpty(oldCode)){
            if(list1.contains(newCode)){
                return true;
            }
        } else{
            if(str1[0].equals(oldCode) && list2.contains(newCode)) {
                return true;
            }
            if(str1[1].equals(oldCode) && str1[0].equals(newCode)) {
                return true;
            }
            if(oldCode.equals(newCode)){
                return true;
            }
            if(str1[1].equals(newCode) && str1[0].equals(oldCode)) {
                return true;
            }
        }
        return false;
    }

    /**
     * 合同号生成
     * 规则：FTM-QD-20180101001
     *
     * @param contractId 合同表主键
     * @return 返回合同号
     */
    private String setContractNo(String contractId){
        //得到今天的第几份正式合同
        Date date2 = new Date();
        String toDay = DateUtil.getDateStr(date2, "yyyy-MM-dd");
        Date toDayLow = DateUtil.getDateForFormat(toDay+" 00:00:00","yyyy-MM-dd HH:mm:ss");
        Date toDayHigh = DateUtil.getDateForFormat(toDay+" 23:59:59","yyyy-MM-dd HH:mm:ss");
        ContractProviderCriteria example = new ContractProviderCriteria();
        ContractProviderCriteria.Criteria c = example.createCriteria();
        c.andIsDelEqualTo(0);
        c.andCreateDateBetween(toDayLow, toDayHigh);
        c.andUploadFileUrlIsNull();
        StringBuilder tmpContract = new StringBuilder();
        tmpContract.append("FTM-QD-");
        tmpContract.append(DateUtil.getDateStr(date2, "yyyyMMdd"));
        int sizeNumber = contractProviderAuditMapper.countByExample2();
        tmpContract.append(StringUtils.fillZeroToInt(sizeNumber,3));

        String contractNo = tmpContract.toString();
        ContractProvider cp = contractProviderMapper.selectByPrimaryKey(contractId);
        cp.setUpdateDate(date2);
        cp.setCreateDate(date2);
        cp.setContractNo(contractNo);
        contractProviderMapper.updateByPrimaryKey(cp);
        return contractNo;
    }

    public void test(String contractId){
        taskExecutor.execute(()-> {
            pdfLogger.info("当前线程："+Thread.currentThread().getName());
            System.out.println("当前线程："+Thread.currentThread().getName());
            uploadPdf(contractId, 0);
        });
    }

    /**
     * 当渠道商初审核通过，生成合同号，
     * 生成word，生成pdf
     * @param contractId 合同主键
     * @param counts 重复三次则停止
     */

    private void uploadPdf(String contractId, int counts){
        counts++;
        //如果这项为假，就一直循环上传
        boolean hasUpload = false;
        pdfLogger.info("待处理合同主键："+contractId);
        ContractProvider cp = contractProviderMapper.selectByPrimaryKey(contractId);
        String contractType = cp.getForDicHtlx();
        String contractNo = cp.getContractNo();
        if(StringUtils.isEmpty(contractNo)){
            contractNo = "test-version"+StringUtils.uuid32().substring(0,6);
        }
        pdfLogger.info("待处理合同号："+contractNo);
        DocUtil docUtil = new DocUtil();
        Map<String, Object> dataMap = new HashMap<String, Object>();
        dataMap.put("contractNo",contractNo);
        dataMap.put("partyB",cp.getPartyB());
        dataMap.put("representativeName",cp.getRepresentativeName());
        dataMap.put("partyAddress",cp.getPartyAddress());
        dataMap.put("incomeDivision",cp.getIncomeDivision());

        String template = "";
        if(contractType.equals(TYPE1+"")){
            template = "template1";
            List<Map<String, Object>> gdbcs = contractProviderGdbcMapper.selectMapByCPId(contractId);
            dataMap.put("ratio1",gdbcs.get(0).get("moneyRatio")+"");
            dataMap.put("ratio2",gdbcs.get(1).get("moneyRatio")+"");
            dataMap.put("ratio3",gdbcs.get(2).get("moneyRatio")+"");
            dataMap.put("ratio4",gdbcs.get(3).get("moneyRatio")+"");
            dataMap.put("fclx",NumberUtils.parseInt(gdbcs.get(0).get("forDicFclx")));
            pdfLogger.info("合同参数："+dataMap.toString());
        }
        if(contractType.equals(TYPE2+"")){
            template = "template2";
            List<Map<String, Object>> gdbcs = contractProviderGdbcMapper.selectMapByCPId(contractId);
            int aRatio = NumberUtils.parseInt(gdbcs.get(0).get("moneyRatio"));
            dataMap.put("ratio1", aRatio);
            dataMap.put("ratio2",100-aRatio);
            pdfLogger.info("合同参数："+dataMap.toString());
        }
        if(contractType.equals(TYPE3+"")){
            template = "template3";
            ContractProviderSdnxCriteria example = new ContractProviderSdnxCriteria();
            ContractProviderSdnxCriteria.Criteria c = example.createCriteria();
            c.andForContractProviderEqualTo(contractId);
            List<Map<String, Object>> cpSdnx = contractProviderSdnxMapper.selectMapByCPId(contractId);
            Map<String, Object> tmpCp = cpSdnx.get(0);
            dataMap.put("region", tmpCp.get("forRegionName")+"");
            int moneys = NumberUtils.parseInt(tmpCp.get("annualFee")+"",360);
            dataMap.put("annualFee", moneys+"");
            int years = NumberUtils.parseInt(tmpCp.get("annualNums")+"",3);
            dataMap.put("annualNum", years+"");
            dataMap.put("fee", moneys*years+"");
            pdfLogger.info("合同参数："+dataMap.toString());
        }
        String path = FileUtils.getWebInfPath();
        String docPath = path + "docs/";
        String docFile = docPath+contractNo+".doc";
        try {
            FileUtils.createDir(docPath);
        } catch (Exception e) {
            e.printStackTrace();
        }
        docUtil.createDoc(dataMap, template, docFile);
        pdfLogger.info("生成WORD成功:"+docFile);
        System.out.println("生成word成功！");
        //转成pdf
        String pdfPath = path + "pdfs/";
        String pdfFile = pdfPath+contractNo+".pdf";
        try {
            FileUtils.createDir(pdfPath);
        } catch (Exception e) {
            e.printStackTrace();
        }
        Word2PDF.doc2pdf(docFile, pdfFile);
        pdfLogger.info("生成PDF成功:"+pdfFile);
        System.out.println("生成pdf成功！");
        //输出pdf文件到文件服务器
        File myFile = new File(pdfFile);
        if(myFile.exists()){
            System.out.println("发送文件出去");
            String out = PostUtil.sendPostWithFile("http://voltmao.com:3000/upload/files", myFile);
            JSONObject tmpObj = JSONObject.parseObject(out);
            int isSuccess = 200;
            String status = "statu";
            if(tmpObj.getInteger(status) == isSuccess){
                //文件发送成功
                hasUpload = true;
                //更新数据库文件下载地址
                String downUrl = tmpObj.getJSONArray("successList").getJSONObject(0).getString("filename");
                cp.setDownloadUrl(downUrl);
                cp.setUpdateDate(new Date());
                contractProviderMapper.updateByPrimaryKey(cp);
            }
            pdfLogger.info("发送PDF文件结果："+out);
            System.out.println("发送文件结果："+out);
        } else{
            pdfLogger.error("文件不存在");
            System.out.println("文件不存在");
        }
        //删除文件
        File docFile1 = new File(docFile);
        if(docFile1.exists() && docFile1.isFile()){
            if(docFile1.delete()){
                pdfLogger.info(contractNo+".doc"+"删除成功");
            }else{
                pdfLogger.error(contractNo+".doc"+"删除失败");
            }
        } else{
            pdfLogger.error(contractNo+".doc"+"不存在");
        }
        File pdfFile1 = new File(pdfFile);
        if(pdfFile1.exists() && pdfFile1.isFile()){
            /*if(pdfFile1.delete()){
                pdfLogger.info(contractNo+".pdf"+"删除成功");
            }else{
                pdfLogger.error(contractNo+".pdf"+"删除失败");
            }*/
        } else{
            pdfLogger.error(contractNo+".pdf"+"不存在");
        }
        //循环
        if(!hasUpload) {
            if(counts <= TYPE3) {
                uploadPdf(contractId, counts);
            } else {
                throw new IllegalArgumentException("系统错误");
            }
        } else {
            pdfLogger.error("合同生成上传处理执行完毕");
        }
    }
}
